#ifndef __DOUBLEPARAMMAP_HPP
#define __DOUBLEPARAMMAP_HPP

#include "datastructureZ/LinkedListZ.h"
#include <map>
#include <vector>

namespace utils {
using namespace datastructureZ;

/**
 * 双键值对映射集（代理） 
 * @param KeyAType 第一键的类型 
 * @param KeyBType 第二键的类型 
 * @param ElementType 映射的数据类型 
 * @param CompareA 第一键的比较（可调用对象）
 * @param CompareB 第二键的比较（可调用对象）
 */
template<class KeyAType, class KeyBType, class ElementType, class CompareA = std::less<KeyAType>, class CompareB = std::less<KeyBType>> class DoubleParamMap {
	protected:typedef LinkedList<ElementType>                    List;
	protected:typedef class List::iterator                       ElementEntry;
	protected:typedef std::map<KeyBType, ElementEntry, CompareB> MapB;
	protected:typedef std::map<KeyAType, MapB, CompareA>         MapA;
	
	protected:List*    list;
	protected:MapA*    mapA;
	protected:unsigned count;
	
	public:DoubleParamMap(void):list(new List), mapA(new MapA), count(0) {
	}
	
	private:void unuse(void) {
		mapA = nullptr;
		list = nullptr;
	}
	
	public:void clear(void) {
		mapA->clear();
		list->clear();
	}
	
	public:~DoubleParamMap(void) {
		delete mapA;
		delete list;
		unuse();
	}
	
	/**
	 * 移动构造 
	 */
	public:DoubleParamMap(DoubleParamMap && another) noexcept: list(another.list), mapA(another.mapA), count(another.count) {
		another.unuse();
	}
	
	/**
	 * 移动赋值 
	 */
	public:DoubleParamMap& operator = (DoubleParamMap && another) noexcept {
		list  = another.list;
		mapA  = another.mapA;
		count = another.count;
		another.unuse();
		return *this;
	}
	
	/**
	 * 阻止拷贝
	 */ 
	public:DoubleParamMap(const DoubleParamMap & another) = delete;
	public:DoubleParamMap& operator = (const DoubleParamMap & another) = delete;
	
	/**
	 * 新增双键值对 
	 * @param keyA 首键 
	 * @param keyB 尾键 
	 * @param elem 要插入的元素 
	 */
	public:void put(const KeyAType& keyA, const KeyBType& keyB, const ElementType& elem) {
		ElementEntry& ee = (*mapA)[keyA][keyB];
		if(ee.loaded()) *ee = elem;
		else {
			ee = list->push_back(elem);
			++count;
		}
	}
	
	/**
	 * 删除双键值对
	 * @param keyA 首键 
	 * @param keyB 尾键 
	 */ 
	public:void erase(const KeyAType& keyA, const KeyBType& keyB) {
		class MapA::iterator itrA = mapA->find(keyA);
		if(itrA == mapA->end()) return;
		class MapB::iterator itrB = (*itrA).second.find(keyB);
		if(itrB == (*itrA).second.end()) return;
		
		(*itrB).second.erase();
		(*itrA).second.erase(itrB);
		--count;
		if((*itrA).second.size() == 0) mapA->erase(itrA);
	}
	
	/**
	 * 将元素插入链表尾部 
	 * @param elem 要插入的元素 
	 * @return 元素在链表中的入口迭代器
	 */
	public:ElementEntry forInsert(const ElementType& elem) {
		++count;
		return list->push_back(elem);
	}
	
	/**
	 * 访问或添加双键值对 ps: dPMap[a][b] = dPMap.forInsert(elem);
	 * @param keyA 首键
	 * @return 二级映射的引用
	 */
	public:MapB& operator [] (const KeyAType& keyA) {
		return (*mapA)[keyA];
	}
	
	/**
	 * 将所有元素缓冲到指定缓冲区
	 * @param buffer 指定的缓冲区
	 * @return 缓冲的元素个数 
	 */
	public:unsigned buff(ElementType* buffer) {
		unsigned buffed = 0; 
		for(class List::iterator itr = list->begin(), end = list->end(); 
			itr != end; ++itr) {
			buffer[buffed++] = *itr;
		}
		return buffed;
	}
	
	public:unsigned buff(std::vector<ElementType>& buffer) {
		for(class List::iterator itr = list->begin(), end = list->end(); 
			itr != end; ++itr) {
			buffer.push_back(*itr);
		}
		return buffer.size();
	}
	
	public:unsigned size(void) {
		return count;
	}
};

};
#endif
